#include "nd_app/nd_app.h"
#include "nd_srvcore/client_map.h"
#include "loginserver.h"
#include "nd_common/nd_rbtree.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "nd_log4c.h"

/* todo
 * manage many types of server,
 * manage many users, use rb tree.
 */
static map_server mapserver[1];

static nd_rwlock id_map_lock;
static rb_node_t *userid_map = NULL;

static nd_rwlock sessionid_map_lock;
static rb_node_t *sessionid_map = NULL;
static log4c_category_t* mycat = NULL;	
static nd_handle listen_handle = NULL;
static NDINT32 usermsg_logout_func(ls_user_t *lsuser, nd_usermsgbuf_t *msg, nd_handle h_listen);

static lua_State *L = NULL;
static int reloadconfig(lua_State *l)
{
	printf("%s\n", __FUNC__);
	return (0);
}
static int lua_addnpc(lua_State *l)
{
	printf("%s\n", __FUNC__);
	return (0);
}

static int lua_init(char *filename)
{
	L = lua_open();
    luaopen_base(L);
//    luaopen_io(L);
    luaopen_string(L);
    luaopen_math(L);

	if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) {
		error(L, "cannot run configuration file: %s", lua_tostring(L, -1));
		return (-1);
	}
	lua_pushcfunction(L, reloadconfig);
	lua_setglobal(L, "reload");
	lua_pushcfunction(L, lua_addnpc);
	lua_setglobal(L, "addnpc");
	
	return (0);
}

static unsigned short get_listenport()
{
	unsigned short listen_port = 0;
	lua_getglobal(L, "listen_port");
    if (!lua_isnumber(L, -1)) {
       error(L, "listen_port should be a number\n");
	   return (0);
	}
	listen_port = lua_tonumber(L, -1);
	return listen_port;
}
static unsigned short get_maxclient()
{
	int max_client = 0;
	lua_getglobal(L, "max_client");
    if (!lua_isnumber(L, -1)) {
       error(L, "max_client should be a number\n");
	   return (0);
	}
	max_client = lua_tonumber(L, -1);
	return max_client;
}


static NDINT32 sendmsg_to_mapserver(NDINT32 server_index, nd_usermsghdr_t *msg, NDINT32 flag)
{
	NDINT32 ret;
	if (server_index >= sizeof(mapserver) / sizeof(mapserver[0])) {
		LOG_ERROR(mycat, "%s %d: mapserver_index[%d] wrong",
			__FUNC__, __LINE__,	server_index);
		return (-1);
	}
	ND_USERMSG_MAXID(msg) = MAXID_SERVER_SERVER;

	if(!nd_connector_valid((nd_netui_handle)mapserver[server_index].base.conn_node)) {
		LOG_ERROR(mycat, "%s %d: mapserver_index[%d] not connect",
			__FUNC__, __LINE__, server_index);
		return (-1);
	}
	ret = nd_sessionmsg_sendex(mapserver[server_index].base.conn_node, msg, flag);			
	return ret;
}

#ifdef SINGLE_THREAD_MOD
static NDINT32 test_accept(NDUINT16 sessionid, SOCKADDR_IN *addr, nd_handle listener)
{
	LOG_DEBUG(mycat, "%s %d: sessionid[%hx]", __FUNC__, __LINE__, sessionid);
	return (0);
}
#else
static NDINT32 test_accept(void *data, SOCKADDR_IN *addr, nd_handle listener)
{
	struct nd_client_map* session = (struct nd_client_map *)data;

	nd_connect_level_set((nd_handle)session, EPL_LOGIN);
	
	LOG_DEBUG(mycat, "%s %d: sessionid[%hx]", __FUNC__, __LINE__,
		session->connect_node.session_id);
	
    return (0);
}
#endif
static NDINT32 pre_deaccept(struct nd_client_map *session, nd_handle listner)
{
	return (0);
}
//这里不能锁，已经锁住的
static NDINT32 test_deaccept(void *data, nd_handle listener)
{
	ls_user_t *lsuser;
	rb_node_t *rb_data;
	NDUINT16 sessionid;
	struct nd_client_map* session = (struct nd_client_map *)data;	
	nd_usermsgbuf_t buf = ND_USERMSG_INITILIZER;

	sessionid = session->connect_node.session_id;
	
	LOG_DEBUG(mycat, "%s %d: sessionid[%hx]", __FUNC__, __LINE__, sessionid);
	nd_rdlock(sessionid_map_lock);
	rb_data = rb_search(sessionid, sessionid_map);
	nd_rdunlock(sessionid_map_lock)
	if (!rb_data) {
		LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid", __FUNC__, __LINE__);
		return 0;
	}
	lsuser = (ls_user_t *)rb_data->data;
	if (!lsuser) {
		return (0);
	}

	nd_wrlock(sessionid_map_lock);
	sessionid_map = rb_erase(sessionid, sessionid_map);
	nd_wrunlock(sessionid_map_lock);
		
	nd_wrlock(id_map_lock);
	userid_map = rb_erase(lsuser->id, userid_map);
	nd_wrunlock(id_map_lock);
	
	usermsg_logout_func(lsuser, &buf, listener);
	free(lsuser);
	return (0);
}

static NDINT32 test_usermsg_func(NDUINT16 sessionid, nd_usermsgbuf_t *msg , nd_handle listener)
{
	LOG_DEBUG(mycat, "%s %d: sessionid[%hx]", __FUNC__, __LINE__, sessionid);	
}

static NDINT32 usermsg_logout_func(ls_user_t *lsuser, nd_usermsgbuf_t *msg, nd_handle h_listen)
{
	NDINT32 ret = -1;
	struct nd_client_map *session;

	session = lsuser->session;

	if(session) {
		if(nd_connector_valid((nd_netui_handle) session)) {
			ND_USERMSG_PARAM(msg) = lsuser->id;
			ND_USERMSG_MAXID(msg) = MAXID_SERVER_SERVER ;
			ND_USERMSG_MINID(msg) = MSG_USER_LEAVE_MAP;
			ret = sendmsg_to_mapserver(lsuser->mapserver_index,
				(struct nd_usermsghdr_t *)msg, ESF_URGENCY);

//			userid_map = rb_erase(lsuser->id, userid_map);
//			sessionid_map = rb_erase(session->connect_node.session_id, sessionid_map);	
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid", __FUNC__, __LINE__);			
		}	   
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
	}

	return (0);
}

static int send_change_map(ls_user_t *ls_user, user_info_t *user_info, NDUINT8 sendto_user)
{
	NDINT32 ret = -1;
	struct nd_client_map *session ;
	nd_usermsgbuf_t buf = ND_USERMSG_INITILIZER;	
	login_ack_t *data = (login_ack_t *)buf.data;
	
	if (!listen_handle) {
		LOG_ERROR(mycat, "%s %d: do not have listen_handle", __FUNC__, __LINE__);				
		return (-1);
	}

	session = ls_user->session;
	if(session) {
		if(nd_connector_valid((nd_netui_handle) session)
			&& ls_user->mapserver_index >= 0
			&& ls_user->mapserver_index < sizeof(mapserver)/sizeof(mapserver[0])) {

			data->result = 0;
			memcpy(&data->user_info, user_info, sizeof(user_info_t));

			ND_USERMSG_LEN(&buf) += sizeof(login_ack_t);			
			ND_USERMSG_PARAM(&buf) = nd_time();
			ND_USERMSG_MAXID(&buf) = MAXID_SERVER_SERVER;
			ND_USERMSG_MINID(&buf) = MSG_USER_CHG_MAP;
			ND_USERMSG_ENCRYPT(&buf) = 0;
			
			ret = sendmsg_to_mapserver(ls_user->mapserver_index,
				(struct nd_usermsghdr_t *)&buf, ESF_URGENCY);

			if (sendto_user == 1) {
				ND_USERMSG_MAXID(&buf) = MAXID_USER_SERVER ;
				ND_USERMSG_MINID(&buf) = MSG_USER_LOGIN_ACK ;
				ret = nd_sessionmsg_sendex((nd_handle)session, (struct nd_usermsghdr_t *)&buf,
					ESF_URGENCY | ESF_ENCRYPT);
			}
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid", __FUNC__, __LINE__);			
		}
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
	}
	return (0);
}

static void change_map(data_t data, void *param)
{
	ls_user_t *ls_user;
	ls_user = (ls_user_t *)data;
//todo
//	send_change_map(ls_user, 0);
}

static NDINT32 alluser_change_map(NDINT32 mapserver_id)
{
	nd_rdlock(id_map_lock);
	rb_travel(userid_map, change_map, (void *)mapserver_id);
	nd_rdunlock(id_map_lock);
	return (0);
}
#ifdef SINGLE_THREAD_MOD
static NDINT32 usermsg_login_func(NDUINT16 sessionid, nd_usermsgbuf_t *msg , nd_handle h_listen)
{
	static NDINT32 index = 0;
	NDINT32 ret = -1;
	user_info_t user_info;
	struct nd_client_map *session;
	ls_user_t *ls_user;
	struct listen_contex *lc;
	struct cm_manager *mamager;

	ls_user = malloc(sizeof(ls_user_t));
	if (!ls_user) {
		LOG_ERROR(mycat, "%s %d: malloc fail", __FUNC__, __LINE__);					
		return (-1);
	}

	lc = (struct listen_contex *) h_listen ;
	mamager = nd_listensrv_get_cmmamager(h_listen);
	
	nd_assert(mamager) ;
	session = (struct nd_client_map *)mamager->lock(mamager, sessionid) ;
	if(session) {
		if(nd_connector_valid((nd_netui_handle) session) && sessionid == session->connect_node.session_id) {
			sprintf(user_info.rolename, "testuser%d", index++);
			user_info.level = 1;
			user_info.id = index;
			user_info.hp = 100;
			user_info.mp = 0;
			user_info.attack = 20;
			user_info.recover = 0;
			user_info.pos_x = 0;
			user_info.pos_y = 0;
			user_info.money = 0;
			user_info.experience = 0;
			user_info.addedattack = 0;
			user_info.addedrecover = 0;
			user_info.rollcall = 0;			

			ls_user->id = index;
			ls_user->mapserver_index = 0;
			ls_user->session = session;

			nd_wrlock(id_map_lock);
			userid_map = rb_insert(ls_user->id,	(data_t)ls_user, userid_map);			
			nd_wrunlock(id_map_lock);
	
			nd_wrlock(sessionid_map_lock);
			sessionid_map = rb_insert(sessionid, (data_t)ls_user, sessionid_map);			
			nd_wrunlock(sessionid_map_lock);

			LOG_DEBUG(mycat, "%s %d: user login id[%d] serverid[%d] session[%p] sessionid[%hx]",
				__FUNC__, __LINE__, ls_user->id,
				ls_user->mapserver_index,
				ls_user->session,
				ls_user->session->connect_node.session_id);
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid sessionid[%d]", __FUNC__, __LINE__, sessionid);			
		}
		mamager->unlock(mamager, sessionid) ;
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session by sessionid[%d]", __FUNC__, __LINE__, sessionid);			
	}
	send_change_map(ls_user, &user_info, 1);
	return (0);
}

static NDINT32 usermsg_normal_func(NDUINT16 sessionid, nd_usermsgbuf_t *msg , nd_handle h_listen)
{
	NDINT32 ret = -1;
	struct nd_client_map *session ;
	ls_user_t *ls_user;
	rb_node_t *rb_data;
	struct listen_contex *lc;
	struct cm_manager *mamager;

	nd_rdlock(sessionid_map_lock)
	rb_data = rb_search(sessionid, sessionid_map);
	nd_rdunlock(sessionid_map_lock)
	if (!rb_data) {
		LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid[%d]",
			__FUNC__, __LINE__, sessionid);
		return (-1);
	}
	ls_user = (ls_user_t *)rb_data->data;

	lc = (struct listen_contex *) h_listen ;
	mamager = nd_listensrv_get_cmmamager(h_listen);
	nd_assert(mamager) ;
	
	session = (struct nd_client_map *)mamager->lock(mamager, sessionid) ;
	if(session) {
		assert(session == ls_user->session);
		if(nd_connector_valid((nd_netui_handle) session)
			&& sessionid == session->connect_node.session_id
			&& ls_user->mapserver_index >= 0
			&& ls_user->mapserver_index < sizeof(mapserver)/sizeof(mapserver[0])) {
			ND_USERMSG_PARAM(msg) = ls_user->id;
			ND_USERMSG_MAXID(msg) = MAXID_SERVER_SERVER;
			ND_USERMSG_ENCRYPT(msg) = 0;
			ret = sendmsg_to_mapserver(ls_user->mapserver_index,
				(struct nd_usermsghdr_t *)msg, ESF_URGENCY);
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid sessionid[%d]", __FUNC__, __LINE__, sessionid);			
		}
		mamager->unlock(mamager, sessionid) ;
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
	}
	
	return (0);
}
#else
static NDINT32 usermsg_login_func(struct nd_client_map *session, nd_usermsgbuf_t *msg , nd_handle h_listen)
{
	static NDINT32 index = 0;
	NDINT32 ret = -1;
	user_info_t user_info;
	ls_user_t *ls_user;
	NDUINT16 sessionid;
	
	ls_user = malloc(sizeof(ls_user_t));
	if (!ls_user) {
		LOG_ERROR(mycat, "%s %d: malloc fail", __FUNC__, __LINE__);					
		return (-1);
	}

	if(session) {
		if(nd_connector_valid((nd_netui_handle) session)) {
			sessionid = session->connect_node.session_id;
			sprintf(user_info.rolename, "testuser%d", index++);
			user_info.level = 1;
			user_info.id = index;
			user_info.hp = 100;
			user_info.mp = 0;
			user_info.attack = 20;
			user_info.recover = 0;
			user_info.pos_x = 0;
			user_info.pos_y = 0;
			user_info.money = 0;
			user_info.experience = 0;
			user_info.addedattack = 0;
			user_info.addedrecover = 0;
			user_info.rollcall = 0;			

			ls_user->id = index;
			ls_user->mapserver_index = 0;
			ls_user->session = session;

			nd_wrlock(id_map_lock);
			userid_map = rb_insert(ls_user->id,	(data_t)ls_user, userid_map);
			nd_wrunlock(id_map_lock);
				
			nd_wrlock(sessionid_map_lock);
			sessionid_map = rb_insert(sessionid, (data_t)ls_user, sessionid_map);			
			nd_wrunlock(sessionid_map_lock);

			LOG_DEBUG(mycat, "%s %d: user login id[%d] serverid[%d] session[%p] sessionid[%hx]",
				__FUNC__, __LINE__, ls_user->id,
				ls_user->mapserver_index,
				ls_user->session,
				ls_user->session->connect_node.session_id);
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid sessionid[%d]", __FUNC__, __LINE__, sessionid);			
		}
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session by sessionid[%d]", __FUNC__, __LINE__, sessionid);			
	}
	send_change_map(ls_user, &user_info, 1);
	return (0);
}

static NDINT32 usermsg_normal_func(struct nd_client_map *session, nd_usermsgbuf_t *msg , nd_handle h_listen)
{
	NDINT32 ret = -1;
	ls_user_t *ls_user;
	rb_node_t *rb_data;

	if (!session)
		return (0);
	
	NDUINT16 sessionid = session->connect_node.session_id;

	nd_rdlock(sessionid_map_lock)
	rb_data = rb_search(sessionid, sessionid_map);
	nd_rdunlock(sessionid_map_lock)	
	if (!rb_data) {
		LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid[%d]",
			__FUNC__, __LINE__, sessionid);
		return (-1);
	}
	ls_user = (ls_user_t *)rb_data->data;

	if (session != ls_user->session) {
		LOG_ERROR(mycat, "%s %d: session is not valid sessionid[%d]",
			__FUNC__, __LINE__, sessionid);			
	}

	if(nd_connector_valid((nd_netui_handle) session)
		&& sessionid == session->connect_node.session_id
		&& ls_user->mapserver_index >= 0
		&& ls_user->mapserver_index < sizeof(mapserver)/sizeof(mapserver[0])) {
		ND_USERMSG_PARAM(msg) = ls_user->id;
		ND_USERMSG_MAXID(msg) = MAXID_SERVER_SERVER;
		ND_USERMSG_ENCRYPT(msg) = 0;
		ret = sendmsg_to_mapserver(ls_user->mapserver_index,
			(struct nd_usermsghdr_t *)msg, ESF_URGENCY);
	} else {
		LOG_ERROR(mycat, "%s %d: session is not valid sessionid[%d]", __FUNC__, __LINE__, sessionid);			
	}
	return (0);
}
#endif
static NDINT32 server_reg_func(NDUINT16 sessionid, nd_usermsgbuf_t *msg , nd_handle h_listen)
{
	return (0);
}

static NDINT32 server_moveto_newmap(nd_handle handle, nd_usermsgbuf_t *msg, nd_handle h_listen)
{
	rb_node_t *rb_data;
	struct nd_client_map *session;
	ls_user_t *ls_user;
	NDUINT32 userid = ND_USERMSG_PARAM(msg);
	moveto_newmap_t *data = (moveto_newmap_t *)msg->data;
	
	if (ND_USERMSG_LEN(msg) != ND_USERMSG_HDRLEN + sizeof(moveto_newmap_t)) {
		LOG_ERROR(mycat, "%s %d: msg len wrong", __FUNC__, __LINE__);		
		return (-1);
	}

	if (userid != data->user_info.id) {
		LOG_ERROR(mycat, "%s %d: userid wrong", __FUNC__, __LINE__);				
		return (-1);
	}
	
	nd_rdlock(id_map_lock);	
	rb_data = rb_search(userid, userid_map);
	nd_rdunlock(id_map_lock);
	if (!rb_data) {
		LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid", __FUNC__, __LINE__);
		return (-1);
	}
	ls_user = (ls_user_t *)rb_data->data;

	if (!listen_handle) {
		LOG_ERROR(mycat, "%s %d: do not have listen_handle", __FUNC__, __LINE__);				
		return (-1);
	}
	
	session = ls_user->session;
	if(session) {
		if(nd_connector_valid((nd_netui_handle) session)) {
				//sendto cur mapserver MSG_USER_LEAVE_MAP
			ls_user->mapserver_index = data->id;
				//sendto new mapserver MSG_USER_CHG_MAP
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid", __FUNC__, __LINE__);			
		}
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
	}

	return (0);
}

static NDINT32 server_normal_ack(nd_handle handle, nd_usermsgbuf_t *msg, nd_handle h_listen)
{
	NDINT32 ret;
	struct nd_client_map *session;
	rb_node_t *rb_data;
	NDUINT32 userid = ND_USERMSG_PARAM(msg);
	ls_user_t *ls_user;
	nd_usermsgbuf_t buf;
	struct listen_contex *lc;
	struct cm_manager *mamager;

	nd_rdlock(id_map_lock);
	rb_data = rb_search(userid, userid_map);
	nd_rdunlock(id_map_lock);
	if (!rb_data) {
		LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid", __FUNC__, __LINE__);
		return (-1);
	}
	ls_user = (ls_user_t *)rb_data->data;


	if (!listen_handle) {
		LOG_ERROR(mycat, "%s %d: do not have listen_handle", __FUNC__, __LINE__);				
		return (-1);
	}

	lc = (struct listen_contex *)ls_user->session->connect_node.srv_root; 
	mamager = nd_listensrv_get_cmmamager(lc);
	nd_assert(mamager) ;
	
	session = (struct nd_client_map *)mamager->lock(mamager, ls_user->session->connect_node.session_id) ;
	if(session) {
		assert(session == ls_user->session);
		if(nd_connector_valid((nd_netui_handle) session)) {
			memcpy(&buf, msg, ND_USERMSG_LEN(msg));
			ret = nd_sessionmsg_sendex((nd_handle)session,
				(nd_usermsghdr_t *)&buf, ESF_URGENCY | ESF_ENCRYPT);
		} else {
			LOG_ERROR(mycat, "%s %d: session is not valid", __FUNC__, __LINE__);			
		}
		mamager->unlock(mamager, session->connect_node.session_id) ;
	} else {
		LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
	}

	return (0);
}

static NDINT32 server_broadcast_func(nd_handle handle, nd_usermsgbuf_t *msg, nd_handle notuse)
{
	NDINT32 i, n, ret;
	NDUINT32 userid;
	rb_node_t *rb_data;
	ls_user_t *ls_user;
	broadcast_info_t *bd_data = (broadcast_info_t *)(msg->data + ND_USERMSG_PARAM(msg));
	struct nd_client_map *session ;
	nd_usermsgbuf_t buf;
	struct listen_contex *lc;
	struct cm_manager *mamager;
	
	if (!listen_handle) {
		LOG_ERROR(mycat, "%s %d: do not have listen_handle", __FUNC__, __LINE__);				
		return (-1);
	}
	
	ND_USERMSG_LEN(msg) -= (sizeof(broadcast_info_t) + sizeof(int) * bd_data->usernum);
	ND_USERMSG_MAXID(msg) = bd_data->real_maxid;
	ND_USERMSG_MINID(msg) = bd_data->real_minid;

	for (i = 0; i < bd_data->usernum; ++i) {
		memcpy(&buf, msg, ND_USERMSG_LEN(msg));
		userid = bd_data->userid[i];
		nd_rdlock(id_map_lock);
		rb_data = rb_search(userid, userid_map);
		nd_rdunlock(id_map_lock);
		if (!rb_data) {
			LOG_ERROR(mycat, "%s %d: can not find rb_data from sessionid", __FUNC__, __LINE__);
			continue;
		}

		lc = (struct listen_contex *)ls_user->session->connect_node.srv_root; 
		mamager = nd_listensrv_get_cmmamager(lc);
		nd_assert(mamager) ;

		ls_user = (ls_user_t *)rb_data->data;
		session = (struct nd_client_map *)mamager->lock(mamager, ls_user->session->connect_node.session_id) ;
		if(session) {
			assert(session == ls_user->session);
			if(nd_connector_valid((nd_netui_handle) session)) {
				ret = nd_sessionmsg_sendex((nd_handle)session,
					(nd_usermsghdr_t *)&buf, ESF_URGENCY | ESF_ENCRYPT);
			} else {
				LOG_ERROR(mycat, "%s %d: session is not valid", __FUNC__, __LINE__);			
			}
			mamager->unlock(mamager, session->connect_node.session_id) ;
		} else {
			LOG_ERROR(mycat, "%s %d: can not find session", __FUNC__, __LINE__);			
		}
	}

	return (0);
}

NDINT32 logic_msg_entry(nd_handle handle, nd_usermsgbuf_t *msg, nd_handle listener)
{
	NDINT8 *buf;

	LOG_DEBUG(mycat, "%s: received message %d ", __FUNC__, ND_USERMSG_MAXID(msg));
	
	if(ND_USERMSG_LEN(msg)>0) {
		buf = (NDINT8 *)msg + sizeof(*msg);
	}
	return 0 ;
}

void init_map_server(map_server *l, NDUINT32 server_id)
{
	memset(l, 0, sizeof(*l));
	l->base.conn_node = nd_object_create("tcp-connector");
	if (!l->base.conn_node) {
		LOG_ERROR(mycat, "%s %d: nd_object_create ret fail[%s]",
			__FUNC__, __LINE__, nd_last_error());
		return;
	}

	l->base.server_id = server_id;
	if (nd_msgtable_create(l->base.conn_node, MSG_CLASS_NUM, MAXID_BASE) != 0) {
		LOG_ERROR(mycat, "%s %d: nd_msgtable_create ret fail[%s]",
			__FUNC__, __LINE__, nd_last_error());
		return;
	}

	nd_msgentry_install(l->base.conn_node, logic_msg_entry,
		MAXID_SYS, SYM_ECHO, 0) ;	
	nd_msgentry_install(l->base.conn_node, server_broadcast_func,
		MAXID_SERVER_SERVER, MSG_BROADCAST_TOUSER, 0);		
	nd_msgentry_install(l->base.conn_node, server_normal_ack,
		MAXID_USER_SERVER, MSG_USER_SCENE_ACK, 0);		
	nd_msgentry_install(l->base.conn_node, server_normal_ack,
		MAXID_SERVER_SERVER, MSG_USER_CHG_MAP_RET, 0);		
	nd_msgentry_install(l->base.conn_node, server_moveto_newmap,
		MAXID_SERVER_SERVER, MSG_USER_LEAVE_MAP, 0);		
}


static void *mapserver_thread(void *param)
{
	NDINT32 ret;
//	nd_usermsgbuf_t sendmsg = ND_USERMSG_INITILIZER;
	map_server *mapserver = (map_server *)param;

	if (!mapserver) {
		LOG_ERROR(mycat, "%s %d: do not have mapserver", __FUNC__, __LINE__) ;
		return;
	}

	nd_handle mapserver_handle = NULL;
	for (;;)
	{
		if (!mapserver_handle) {
			if (nd_connector_openex(mapserver->base.conn_node, "127.0.0.1", 12346)) {
				ndprintf(_NDT("%s %d: connect error :%s!\n"), __FUNC__, __LINE__, nd_last_error()) ;
				LOG_ERROR(mycat, "%s %d: connect error :%s!",
					__FUNC__, __LINE__, nd_last_error()) ;
				nd_sleep(10 * 1000);
				continue;
			} else {
				mapserver_handle = mapserver->base.conn_node;
				LOG_DEBUG(mycat, "connect success!");
			}
		}

		ret = nd_connector_update(mapserver_handle, 10*1000);
/*		ret = nd_connector_waitmsg(mapserver_handle, (nd_packetbuf_t *)&sendmsg, 10*1000);

		if(ret > 0) {
			nd_translate_message(mapserver_handle, (nd_packhdr_t*) &sendmsg) ;
		}
		else if(-1==ret) {
*/
		if (ret < 0 || (ret == 0 && (struct nd_tcp_node *)mapserver_handle->myerrno != NDERR_SUCCESS)) {
			ndprintf(_NDT("closed by remote ret = 0\n")) ;
			LOG_DEBUG(mycat, "%s %d: closed by remote[%d]!",
				__FUNC__, __LINE__,
				(struct nd_tcp_node *)mapserver_handle->myerrno);
			mapserver_handle = NULL;
			nd_connector_reset(mapserver->base.conn_node);			
			continue ;
		}
		else {
//			ndprintf(_NDT("wait time out ret = %d\npress any key to continue\n"), ret) ;
		}
	}

	LOG_DEBUG(mycat, "%s %d: mapserver_thread end", __FUNC__, __LINE__) ;
	return (0);
}

static void show_ls_userinfo(data_t data, void *param)
{
	ls_user_t *ls_user = (ls_user_t *)data;
	ndprintf(_NDT("id[%d] serverid[%d] session[%p] sessionid[%hx]\n"),
		ls_user->id,
		ls_user->mapserver_index,
		ls_user->session,
		ls_user->session->connect_node.session_id);
}

int main(int argc, char *argv[])
{
    char ch;
    int ret;
	int i;
	struct listen_contex *lc;
	
	log4c_init();
	mycat = log4c_category_get("loginserver");	
	LOG_DEBUG(mycat, "Debugging app 1 - loop %d", 10);
#if 0
	start_server(argc, argv);
	wait_services() ;
	printf_dbg("leave wait server\n") ;
	end_server(0) ;
	printf_dbg("program exit from main\n Press ANY KEY to continue\n") ;
	getch();
#else	
	
//	start_server(argc, argv);

	nd_rwlock_init(&sessionid_map_lock);
	nd_rwlock_init(&id_map_lock);	
	ret = init_module();

	lua_init("config.lua");
	
	ret = create_rsa_key();
	listen_handle = nd_object_create("listen-ext") ;
#ifdef ND_DEBUG
	nd_set_connection_timeout(listen_handle, 60 * 60);
#endif	
	for (i = 0; i < sizeof(mapserver)/sizeof(mapserver[0]); ++i) {
		init_map_server(&mapserver[i], SERVER_TYPE_MAP | MAP_SERVER_NOVICE + i);
		nd_createthread(mapserver_thread, &mapserver[i], NULL, 0);
	}

#ifdef SINGLE_THREAD_MOD	
	nd_listensrv_set_single_thread(listen_handle) ;
#endif
	ret = nd_listensrv_session_info(listen_handle, get_maxclient(), 0);

#ifdef SINGLE_THREAD_MOD
	ND_SET_ONCONNECT_ENTRY(listen_handle, test_accept, NULL, NULL) ;
	lc = (struct listen_contex *)listen_handle ;
	lc->tcp.pre_out_callback = test_deaccept ;
#else
	nd_listensrv_set_entry(listen_handle, test_accept, test_deaccept, NULL);
#endif

	nd_srv_msgtable_create(listen_handle, MAXID_SYS + 1, 0);

	install_start_session(listen_handle);
	ND_INSTALL_HANDLER(listen_handle, srv_broadcast_handler,
		MAXID_SYS, SYM_BROADCAST, EPL_CONNECT) ;
	nd_net_set_crypt((nd_netcrypt)nd_TEAencrypt, (nd_netcrypt)nd_TEAdecrypt, sizeof(tea_v)) ;
	
	ND_INSTALL_HANDLER(listen_handle, test_usermsg_func, MAXID_SYS, SYM_ECHO, 0);
	ND_INSTALL_HANDLER(listen_handle, usermsg_login_func, MAXID_USER_SERVER, MSG_USER_LOGIN_REQ, 0);

//	ND_INSTALL_HANDLER(listen_handle, usermsg_normal_func, MAXID_USER_SERVER, MSG_USER_MOVE_REQ, 0);
	ND_INSTALL_HANDLER(listen_handle, usermsg_normal_func, MAXID_USER_SERVER, MSG_USER_ACTION_REQ, 0);
	ND_INSTALL_HANDLER(listen_handle, usermsg_normal_func, MAXID_USER_SERVER, MSG_USER_SCENE_REQ, 0);

	ND_INSTALL_HANDLER(listen_handle, server_reg_func, MAXID_SERVER_SERVER, MSG_SERVER_REG, 0);


		//nd_singleth_msghandler
		//nd_do_netmsg
	
	ret = nd_listensrv_open(get_listenport(), listen_handle);

	while (1) {
		if(kbhit()) {
			ch = getch() ;
			if(ND_ESC==ch){
				printf_dbg("you are hit ESC, program eixt\n") ;
				break ;
			}
			switch (ch)
			{
				case 'a':
					nd_rdlock(id_map_lock);
					rb_travel(userid_map, show_ls_userinfo, NULL);
					nd_rdunlock(id_map_lock);

					ndprintf(_NDT("==================\n"));

					nd_rdlock(sessionid_map_lock);
					rb_travel(sessionid_map, show_ls_userinfo, NULL);
					nd_rdunlock(sessionid_map_lock);
					break;
				default:
					break;
			}
		}
		else {
			nd_sleep(1000) ;
		}
	}

	nd_srv_msgtable_destroy(listen_handle);

	nd_object_destroy(listen_handle, 0);
	destroy_rsa_key();
	destroy_module();
#endif
	if (log4c_fini()){
		printf("log4c_fini() failed");
	}
    return 0;
}


